package controller

import (
	"CampusCloudAid/dao/mysql"
	"CampusCloudAid/logic"
	"CampusCloudAid/models"
	"CampusCloudAid/pkg/jwt"
	pkg "CampusCloudAid/pkg/weixinpay"
	"context"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"gorm.io/gorm"

	"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
	"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
	"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments"

	"github.com/wechatpay-apiv3/wechatpay-go/services/payments/native"

	"github.com/wechatpay-apiv3/wechatpay-go/core"

	"github.com/gin-gonic/gin"
)

//支付功能，应该先让用户在前端输入充值金额，点击上传，后端获取到
/* 接口地址：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml
   接口说明：商户系统先调用该接口在微信支付服务后台生成预支付交易单，返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。 */
//{
//"appid": "wxd82cf42e3b0aff22", ///请求基础下单接口时请注意APPID的应用属性，例如公众号场景下，需使用应用属性为公众号的服务号APPID
//"mchid": "1674186447", ///商户号,要与请求头保持一致
//"description": "Image形象店-深圳腾大-QQ公仔", ///商品描述
//"out_trade_no": "Tencentwechatpay0000006", ///户系统内部订单号，只能是数字、大小写字母_-*且在同一个商户号下唯一
//"time_expire": "2024-04-18T23:59:59+08:00",
///*订单失效时间，遵循rfc3339标准格式，格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE，yyyy-MM-DD表示年月日，T出现在字符串中，表示time元素的开头，HH:mm:ss表示时分秒，TIMEZONE表示时区（+08:00表示东八区时间，领先UTC8小时，即北京时间）。例如：2015-05-20T13:29:35+08:00表示，北京时间2015年5月20日 13点29分35秒。 */
//"attach": "附加数据", ///附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用，实际情况下只有支付完成状态才会返回该字段。
//"notify_url": "https://wxpay.xinxuecheng.cn",
///* 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。 公网域名必须为https，如果是走专线接入，使用专线NAT IP或者私有回调域名可使用http */
//"support_fapiao": false, ///传入true时，支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能，传此字段才可生效。
//"amount": {
//"total": 1, ///订单总金额，单位为“分”
//"currency": "CNY" /// CNY：人民币，境内商户号仅支持人民币。
//},
//"settle_info": {
//"profit_sharing": false ///是否指定分账
//}
//}

// 定义微信支付订单信息结构体
type WeChatOrder struct {
	MchID       string `json:"mchid"`
	OutTradeNo  string `json:"out_trade_no"`
	AppID       string `json:"appid"`
	Description string `json:"description"`
	NotifyURL   string `json:"notify_url"`
	Amount      struct {
		Total    int    `json:"total"`
		Currency string `json:"currency"`
	} `json:"amount"`
}

// RechargeController 处理充值订单相关的请求
//
//	type RechargeController struct {
//		RechargeLogic *logic.RechargeLogic
//	}
//
// 创建订单并发送给微信支付接口
func CreateAndSendOrder(c *gin.Context) {
	// 初始化微信支付
	client := pkg.InitWeChatPay()

	// 从 token 中获取用户ID
	userID, err := jwt.GetUserId(c)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
		return
	}

	// 解析 JSON 请求体以获取充值金额
	var input struct {
		Amount float64 `json:"amount" binding:"required"`
	}
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 调用逻辑层函数创建充值订单
	recharge, err := logic.CreateRecharge(userID, input.Amount)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	svc := native.NativeApiService{Client: client}
	// 构建微信支付订单信息
	resp, result, err := svc.Prepay(c,
		native.PrepayRequest{
			Appid:       core.String(pkg.AppID),
			Mchid:       core.String(pkg.MchID),
			Description: core.String("校园云互助充值"),
			OutTradeNo:  core.String(strconv.FormatInt(recharge.Id, 10)),
			NotifyUrl:   core.String(pkg.NotifyURL),
			Amount: &native.Amount{
				Total: core.Int64(int64(input.Amount * 100)), // 一分钱为1
			},
		},
	)
	// 发送订单信息给微信支付接口
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 检查响应状态
	if result.Response.StatusCode != http.StatusOK {
		c.JSON(result.Response.StatusCode, gin.H{"error": "支付请求失败"})
		return
	}

	// 返回支付结果给前端
	c.JSON(http.StatusOK, gin.H{"code_url": resp.CodeUrl})
	return
}

type PaymentSuccessNotification struct { //回调数据；+
	ID           string `json:"id"`
	CreateTime   string `json:"create_time"`
	ResourceType string `json:"resource_type"`
	EventType    string `json:"event_type"`
	Summary      string `json:"summary"`
	Resource     struct {
		OriginalType   string `json:"original_type"`
		Algorithm      string `json:"algorithm"`
		Ciphertext     string `json:"ciphertext"`
		AssociatedData string `json:"associated_data"`
		Nonce          string `json:"nonce"`
	} `json:"resource"`
}

//// 处理接收到的微信支付通知
//func HandleWeChatPayNotification(c *gin.Context) {
//	var paymentNotification PaymentSuccessNotification
//	if err := c.ShouldBindJSON(&paymentNotification); err != nil {
//		fmt.Println("Error:", err)
//		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
//		return
//	}
//	fmt.Printf("Received payment success notification: %+v\n", paymentNotification)
//
//	// 从请求头中获取微信支付通知的相关参数
//	signature := c.GetHeader("Wechatpay-Signature")
//	timestamp := c.GetHeader("Wechatpay-Timestamp")
//	nonce := c.GetHeader("Wechatpay-Nonce")
//	//fmt.Println(signature)
//	//fmt.Println(timestamp)
//	//fmt.Println(nonce)
//	// 从请求体中读取通知数据
//	body, err := ioutil.ReadAll(c.Request.Body)
//	if err != nil {
//		c.String(http.StatusInternalServerError, "Failed to read request body")
//		return
//	}
//
//	// 根据微信支付通知的签名、时间戳、随机字符串和请求体，以及你的 API 密钥进行验证
//	if pkg.VerifyWeChatPayNotification(signature, timestamp, nonce, string(body), pkg.MchAPIv3Key) {
//		// 签名验证通过，继续处理通知内容
//		fmt.Printf("Received payment success notification: %+v\n", body)
//		// 处理业务逻辑...
//		fmt.Printf("接收验签成功！！！")
//
//		// 返回处理结果给微信支付服务器
//		c.String(http.StatusOK, "success")
//	} else {
//		// 签名验证失败，拒绝通知
//		c.String(http.StatusBadRequest, "fail")
//	}
//}

// 处理接收到的微信支付返回的通知
func HandleWeChatPayNotification(c *gin.Context) {
	// 1. 注册下载器并初始化通知处理器
	err := downloader.MgrInstance().RegisterDownloaderWithPrivateKey(context.Background(), pkg.MchPrivateKey, pkg.MchCertificateSerialNumber, pkg.MchID, pkg.MchAPIv3Key)
	if err != nil {
		fmt.Println("Failed to register downloader:", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to register downloader"})
		return
	}
	certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(pkg.MchID)
	handler := notify.NewNotifyHandler(pkg.MchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
	//fmt.Println("Request body:", string(body))

	// 2. 解析微信支付通知
	transaction := new(payments.Transaction)
	notifyReq, err := handler.ParseNotifyRequest(context.Background(), c.Request, transaction)
	if err != nil {
		fmt.Println("Failed to parse notify request:", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse notify request"})
		return
	}

	// 处理通知内容
	fmt.Println("Received payment notification summary:", notifyReq.Summary)
	fmt.Println(transaction) //全部数据

	// 处理业务逻辑...
	// 查询数据库中的订单
	var recharge models.Recharge
	if err := mysql.Conn.Where("id = ?", transaction.OutTradeNo).First(&recharge).Error; err != nil {
		fmt.Println("Error fetching recharge:", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Error fetching recharge"})
		return
	}
	// 检查订单金额是否相符
	if float64(recharge.Amount)*100 != float64(*transaction.Amount.Total) {
		fmt.Println("Amount mismatch")
		c.JSON(http.StatusBadRequest, gin.H{"error": "Amount mismatch"})
		return
	}
	// 更新数据库记录
	if err := mysql.Conn.Model(&recharge).Updates(map[string]interface{}{
		"get_time": time.Now(),
		"status":   "已支付",
	}).Error; err != nil {
		fmt.Println("Error updating recharge:", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Error updating recharge"})
		return
	}
	// 将充值金额添加到用户的可提现金额中
	if err := mysql.Conn.Model(&models.AccountBalance{}).Where("user_id = ?", recharge.UserId).Update("with_drawable", gorm.Expr("with_drawable + ?", recharge.Amount)).Error; err != nil {
		fmt.Println("Error updating user balance:", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Error updating user balance"})
		return
	}
	// 返回处理结果给微信支付服务器
	c.Status(http.StatusOK)
	{
		// 4. 保存流水记录到数据库
		moneyFlow := models.MoneyFlow{

			FromUserID:  1,               // 设置为1表示系统生成的充值
			ToUserID:    recharge.UserId, // 充值的用户ID
			Amount:      recharge.Amount, // 充值的金额
			ArrivalTime: time.Now(),      // 当前时间
			Status:      "充值",            // 充值状态
			TaskID:      recharge.Id,     // 充值订单的ID
		}
		err := mysql.CreateFlow(moneyFlow)
		if err != nil {
			return
		}
	}

	if err != nil {
		// 返回失败的JSON响应
		c.JSON(http.StatusOK, gin.H{
			"code":    "FAIL",
			"message": "失败",
		})
	}
	//设置流水表数据：充值：需要传入用户id，

}
